home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
MPW_TOOL
/
TOOLS
/
TOOLS_WI
/
ICON_8
/
ICONX_FO
/
FSYS.C
< prev
next >
Wrap
Text File
|
1990-04-01
|
24KB
|
1,142 lines
/*
* File: fsys.c
* Contents: close, exit, getenv, open, read, reads, remove, rename, [save],
* seek, stop, [system], where, write, writes, [getch, getche, kbhit]
*/
#include "::h:config.h"
#include "::h:rt.h"
#include "rproto.h"
#ifdef PreProcess
/* include(../M4/fncs.m4) /* */
/* */
#endif /* PreProcess */
#if MICROSOFT || SCO_XENIX
#define BadCode
#endif /* MICROSOFT || SCO_XENIX */
#ifdef XENIX_386
#define register
#endif /* XENIX_386 */
#if MACINTOSH
#if MPW
#include <FCntl.h>
#include <IOCtl.h>
#include <Files.h>
#define isatty(fd) (!ioctl((fd), FIOINTERACTIVE))
/*
* myfflush() -- Permits environment variable option as to whether
* console output should be automatically flushed after each line of
* output.
*/
int
myfflush(f)
FILE *f;
{
static short initialized = 0;
static short nolineflush;
if (!initialized) {
initialized = 1;
nolineflush = getenv("NOLINEFLUSH") != NULL;
}
return nolineflush ? 0 : fflush(f);
}
#define fflush(f) (myfflush(f))
#endif /* MPW */
#endif /* MACINTOSH */
/*
* close(f) - close file f.
*/
FncDcl(close,1)
{
FILE *f;
/*
* Arg1 must be a file.
*/
if (Arg1.dword != D_File)
RunErr(105, &Arg1);
/*
* Close Arg1, using fclose or pclose as appropriate.
*/
#if UNIX || VMS
if (BlkLoc(Arg1)->file.status & Fs_Pipe) {
BlkLoc(Arg1)->file.status = 0;
MakeInt((long)((pclose(BlkLoc(Arg1)->file.fd) >> 8) & 0377), &Arg0);
Return;
}
else
#endif /* UNIX || VMS */
f = BlkLoc(Arg1)->file.fd;
fclose(f);
BlkLoc(Arg1)->file.status = 0;
/*
* Return the closed file.
*/
Arg0 = Arg1;
Return;
}
/*
* exit(status) - exit process with specified status, defaults to 0.
*/
FncDcl(exit,1)
{
if (defshort(&Arg1, NormalExit) == Error)
RunErr(0, NULL);
c_exit((int)IntVal(Arg1));
}
/*
* getenv(s) - return contents of environment variable s
*/
FncDcl(getenv,1)
{
#ifndef EnvVars
RunErr(-121, NULL);
#else /* EnvVars */
register char *p;
register word len;
char sbuf[256];
/*
* Make a C-style string out of Arg1
*/
switch (cvstr(&Arg1, sbuf)) {
case Cvt: /* Already converted to a C-style string */
break;
case NoCvt:
qtos(&Arg1, sbuf);
break;
default:
RunErr(103, &Arg1);
}
if ((p = getenv(StrLoc(Arg1))) != NULL) { /* get environment variable */
len = strlen(p);
if (strreq(len) == Error)
RunErr(0, NULL);
StrLen(Arg0) = len;
StrLoc(Arg0) = alcstr(p, len);
Return;
}
else /* fail if not in environment */
Fail;
#endif /* EnvVars */
}
/*
* open(s1,s2) - open file s1 with specification s2.
*/
FncDcl(open,2)
{
register word slen;
register int i;
register char *s;
int status;
char mode[4];
extern FILE *fopen();
char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
char *openstring;
FILE *f;
/*
* The following code is operating-system dependent [@fsys.01]. Make
* declarations as needed for opening files.
*/
#if PORT
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || MVS || VM
/* nothing is needed */
#endif /* AMIGA || MACINTOSH */
#if ATARI_ST || HIGHC_386 || MSDOS || OS2
char untranslated;
#endif /* ATARI_ST || HIGHC_386 || ... */
#if MACINTOSH
#if LSC
char untranslated;
#endif /* LSC */
#endif /* MACINTOSH */
#if UNIX || VMS
extern FILE *popen();
#endif /* UNIX || VMS */
/*
* End of operating-system specific code.
*/
/*
* Arg1 must be a string and a C string copy of it is also needed.
* Make it a string if it is not one; make a C string if Arg1 is
* a string.
*/
switch (cvstr(&Arg1, sbuf1)) {
case Cvt:
openstring = StrLoc(Arg1);
if (strreq(StrLen(Arg1)) == Error)
RunErr(0, NULL);
StrLoc(Arg1) = alcstr(StrLoc(Arg1), StrLen(Arg1));
break;
case NoCvt:
tended[1] = Arg1;
ntended = 1;
qtos(&tended[1], sbuf1);
openstring = StrLoc(tended[1]);
break;
default:
RunErr(103, &Arg1);
}
/*
* s2 defaults to "r".
*/
if (defstr(&Arg2, sbuf2, &letr) == Error)
RunErr(0, NULL);
if (blkreq((word)sizeof(struct b_file)) == Error)
RunErr(0, NULL);
status = 0;
/*
* The following code is operating-system dependent [@fsys.02]. Provide
* declaration for untranslated line-termination mode, if supported.
*/
#if PORT
/* nothing to do */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA
/* translated mode could be supported, but is not now */
#endif /* AMIGA */
#if ATARI_ST || HIGHC_386 || MSDOS || OS2
untranslated = 0;
#endif /* ATARI_ST || HIGHC_386 || ... */
#if MACINTOSH
#if LSC
untranslated = 0;
#endif /* LSC */
#endif /* MACINTOSH */
#if MVS || UNIX || VM || VMS
/* nothing to do */
#endif /* UNIX || VMS */
/*
* End of operating-system specific code.
*/
/*
* Scan Arg2, setting appropriate bits in status. Produce a run-time error
* if an unknown character is encountered.
*/
s = StrLoc(Arg2);
slen = StrLen(Arg2);
for (i = 0; i < slen; i++) {
switch (*s++) {
case 'a':
case 'A':
status |= Fs_Write|Fs_Append;
continue;
case 'b':
case 'B':
status |= Fs_Read|Fs_Write;
continue;
case 'c':
case 'C':
status |= Fs_Create|Fs_Write;
continue;
case 'r':
case 'R':
status |= Fs_Read;
continue;
case 'w':
case 'W':
status |= Fs_Write;
continue;
/*
* The following code is operating-system dependent [@fsys.03]. Handle
* untranslated line-terminator mode and pipes, if supported.
*/
#if PORT
case 't':
case 'T':
case 'u':
case 'U':
continue; /* no-op */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || MVS || VM
case 't':
case 'T':
case 'u':
case 'U':
continue; /* no-op */
#endif /* AMIGA || MVS || VM */
#if ATARI_ST || HIGHC_386 || MSDOS || OS2
case 't':
case 'T':
untranslated = 0;
continue;
case 'u':
case 'U':
untranslated = 1;
continue;
#endif /* ATARI_ST || HIGHC_386 || ... */
#if MACINTOSH
#if LSC
case 't':
case 'T':
untranslated = 0;
continue;
case 'u':
case 'U':
untranslated = 1;
continue;
#endif /* LSC */
#endif /* MACINTOSH */
#if UNIX || VMS
case 't':
case 'T':
case 'u':
case 'U':
continue; /* no-op */
case 'p':
case 'P':
status |= Fs_Pipe;
continue;
#endif /* UNIX || VMS */
/*
* End of operating-system specific code.
*/
default:
RunErr(209, &Arg2);
}
}
/*
* Construct a mode field for fopen/popen.
*/
mode[0] = '\0';
mode[1] = '\0';
mode[2] = '\0';
mode[3] = '\0';
if ((status & (Fs_Read|Fs_Write)) == 0) /* default: read only */
status |= Fs_Read;
if (status & Fs_Create)
mode[0] = 'w';
else if (status & Fs_Append)
mode[0] = 'a';
else if (status & Fs_Read)
mode[0] = 'r';
else
mode[0] = 'w';
/*
* The following code is operating-system dependent [@fsys.04]. Handle open
* modes.
*/
#if PORT
if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write))
mode[1] = '+';
Deliberate Syntax Error
#endif /* PORT */
#if ATARI_ST
if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write)) {
mode[1] = '+';
mode[2] = untranslated ? 'b' : 'a';
}
else mode[1] = untranslated ? 'b' : 'a';
#endif /* ATARI_ST */
#if HIGHC_386 || OS2
if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write)) {
mode[1] = '+';
mode[2] = untranslated ? 'b' : 't';
}
else mode[1] = untranslated ? 'b' : 't';
#endif /* HIGHC_386 || OS2 */
#if MACINTOSH
#if LSC
if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write)) {
mode[1] = '+';
if (untranslated)
mode[2] = 'b';
}
else if (untranslated)
mode[1] = 'b';
#endif /* LSC */
#endif /* MACINTOSH */
#if MSDOS
#if MICROSOFT || TURBO
if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write)) {
mode[1] = '+';
mode[2] = untranslated ? 'b' : 't';
}
else mode[1] = untranslated ? 'b' : 't';
#endif /* MICROSOFT || TURBO */
#if LATTICE || MWC
if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write)) {
mode[1] = '+';
if (untranslated)
mode[2] = 'b';
}
else if (untranslated)
mode[1] = 'b';
#endif /* LATTICE || MWC */
#endif /* HIGHC_386 || MSDOS */
#if AMIGA || MACINTOSH || MVS || UNIX || VM || VMS
if ((status & (Fs_Read|Fs_Write)) == (Fs_Read|Fs_Write))
mode[1] = '+';
#endif /* AMIGA || MACINTOSH || UNIX || VMS */
/*
* End of operating-system specific code.
*/
/*
* Open the file with fopen or popen.
*/
#if UNIX || VMS
if (status & Fs_Pipe) {
if (status != (Fs_Read|Fs_Pipe) && status != (Fs_Write|Fs_Pipe))
RunErr(209, &Arg2);
f = popen(openstring, mode);
}
else
#endif /* UNIX || VMS */
f = fopen(openstring, mode);
/*
* Fail if the file cannot be opened.
*/
if (f == NULL)
Fail;
#if MACINTOSH
#if MPW
/* Set file type and creator. */
{
FInfo info;
if (getfinfo(openstring,0,&info) == 0) {
if (status & Fs_Write && info.fdType == 0 && info.fdCreator == 0) {
info.fdType = 'TEXT';
info.fdCreator = 'MPS ';
setfinfo(openstring,0,&info);
}
}
}
#endif /* MPW */
#endif /* MACINTOSH */
/*
* Return the resulting file value.
*/
Arg0.dword = D_File;
BlkLoc(Arg0) = (union block *) alcfile(f, status, &Arg1);
ntended = 0;
Return;
}
/*
* read(f) - read line on file f.
*/
FncDcl(read,1)
{
register word slen, rlen;
register char *sp;
int status;
static char sbuf[MaxReadStr];
FILE *f;
/*
* Default Arg1 to &input.
*/
if (deffile(&Arg1, &input) == Error)
RunErr(0, NULL);
/*
* Get a pointer to the file and be sure that it is open for reading.
*/
f = BlkLoc(Arg1)->file.fd;
status = (int)BlkLoc(Arg1)->file.status;
if ((status & Fs_Read) == 0)
RunErr(212, &Arg1);
/*
* Use getstrg to read a line from the file, failing if getstrg
* encounters end of file. [[ What about -2?]]
*/
StrLen(Arg0) = 0;
do {
if ((slen = getstrg(sbuf,MaxReadStr,f)) == -1)
Fail;
/*
* Allocate the string read and make Arg0 a descriptor for it.
*/
rlen = slen < 0 ? (word)MaxReadStr : slen;
if (strreq(rlen) == Error)
RunErr(0, NULL);
sp = alcstr(sbuf,rlen);
if (StrLen(Arg0) == 0)
StrLoc(Arg0) = sp;
StrLen(Arg0) += rlen;
} while (slen < 0);
Return;
}
/*
* reads(f,i) - read i characters on file f.
*/
FncDcl(reads,2)
{
register word cnt;
long tally;
int status;
FILE *f;
/*
* Arg1 defaults to &input and Arg2 defaults to 1 (character).
*/
if ((deffile(&Arg1, &input) == Error) ||
(defshort(&Arg2, 1) == Error))
RunErr(0, NULL);
/*
* Get a pointer to the file and be sure that it is open for reading.
*/
f = BlkLoc(Arg1)->file.fd;
status = (int)BlkLoc(Arg1)->file.status;
if ((status & Fs_Read) == 0)
RunErr(212, &Arg1);
/*
* Be sure that a positive number of bytes is to be read.
*/
if ((cnt = IntVal(Arg2)) <= 0)
RunErr(205, &Arg2);
/*
* Ensure that enough space for the string exists and read it directly
* into the string space. (By reading directly into the string space,
* no arbitrary restrictions are placed on the size of the string that
* can be read.) Make Arg0 a descriptor for the string and return it.
*/
if (strreq(cnt) == Error)
RunErr(0, NULL);
if (strfree + cnt > strend)
syserr("reads allocation botch");
StrLoc(Arg0) = strfree;
#if AMIGA
/*
* The following code is special for Lattice 4.0 -- it was different
* for Lattice 3.10. It probably won't work correctly with other
* C compilers.
*/
if (IsInteractive(_ufbs[fileno(f)].ufbfh)) {
if ((cnt = read(fileno(f),StrLoc(Arg0),cnt)) <= 0)
Fail;
StrLen(Arg0) = cnt;
alcstr(NULL, cnt);
Return;
}
#endif /* AMIGA */
tally = longread(StrLoc(Arg0),sizeof(char),cnt,f);
if (tally == 0)
Fail;
StrLen(Arg0) = tally;
alcstr(NULL, (word)tally);
Return;
}
/*
* remove(s) - remove the file named s.
*/
FncDcl(remove,1)
{
char sbuf[MaxCvtLen];
/*
* Make a C-style string out of Arg1
*/
switch (cvstr(&Arg1, sbuf)) {
case Cvt: /* Already converted to a C-style string */
break;
case NoCvt:
qtos(&Arg1, sbuf);
break;
default:
RunErr(103, &Arg1);
}
if (unlink(StrLoc(Arg1)) != 0)
Fail;
Arg0 = nulldesc;
Return;
}
/*
* rename(s1,s2) - rename the file named s1 to have the name s2.
*/
FncDcl(rename,2)
{
char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
/*
* Make a C-style string out of Arg1
*/
switch (cvstr(&Arg1, sbuf1)) {
case Cvt: /* Already converted to a C-style string */
break;
case NoCvt:
qtos(&Arg1, sbuf1);
break;
default:
RunErr(103, &Arg1);
}
/*
* Make a C-style string out of Arg2
*/
switch (cvstr(&Arg2, sbuf2)) {
case Cvt: /* Already converted to a C-style string */
break;
case NoCvt:
qtos(&Arg2, sbuf2);
break;
default:
RunErr(103, &Arg2);
}
/*
* The following code is operating-system dependent [@fsys.05]. Rename the
* file, and fail if unsuccessful.
*/
#if PORT
/* need something */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || MSDOS || MVS || OS2 || VM || VMS
{
if (rename(StrLoc(Arg1),StrLoc(Arg2)) != 0)
Fail;
}
#endif /* AMIGA || ATARI_ST ... */
#if UNIX
if (link(StrLoc(Arg1),StrLoc(Arg2)) != 0)
Fail;
if (unlink(StrLoc(Arg1)) != 0) {
unlink(StrLoc(Arg2)); /* try to undo partial rename */
Fail;
}
#endif /* UNIX */
/*
* End of operating-system specific code.
*/
Arg0 = nulldesc;
Return;
}
#ifdef ExecImages
/*
* save(s) - save the run-time system in file s
*/
FncDcl(save,1)
{
char sbuf[MaxCvtLen];
int f, fsz;
dumped = 1;
/* if (ChkNull(Arg1)) { abort(); } */
/*
* Make a C-style string out of Arg1.
*/
switch (cvstr(&Arg1, sbuf)) {
case Cvt: /* Already converted to a C-style string */
break;
case NoCvt:
qtos(&Arg1, sbuf);
break;
default:
RunErr(103, &Arg1);
}
/*
* Open the file for the executable image.
*/
f = creat(StrLoc(Arg1), 0777);
if (f == -1)
Fail;
fsz = wrtexec(f);
/*
* It happens that most wrtexecs don't check the system call return
* codes and thus they'll never return -1. Nonetheless...
*/
if (fsz == -1)
Fail;
/*
* Return the size of the data space.
*/
MakeInt(fsz, &Arg0);
Return;
}
#endif /* ExecImages */
/*
* seek(file,position) - seek to byte byte position in file.
* [[ What about seek error ? ]]
*/
FncDcl(seek,2)
{
long l1;
FILE *fd;
if (Arg1.dword != D_File)
RunErr(-105, NULL);
if (defint(&Arg2, &l1, 1L) == Error)
RunErr(0, NULL);
fd = BlkLoc(Arg1)->file.fd;
if (BlkLoc(Arg1)->file.status == 0)
Fail;
if (l1 > 0) {
if (fseek(fd, l1 - 1, 0) == -1)
Fail;
}
else {
if (fseek(fd, l1, 2) == -1)
Fail;
}
Arg0 = Arg1;
Return;
}
/*
* stop(a,b,...) - write arguments (starting on error output) and stop.
*/
FncDclV(stop)
{
register word n;
char sbuf[MaxCvtLen];
FILE *f;
#ifdef BadCode
struct descrip temp;
#endif /* BadCode */
f = stderr;
ntended = 0;
/*
* Loop through arguments.
*/
for (n = 1; n <= nargs; n++) {
#ifdef BadCode
temp = Arg(n); /* workaround for Microsoft C bug */
tended[1] = temp;
#else /* BadCode */
tended[1] = Arg(n);
#endif /* BadCode */
if (tended[1].dword == D_File) {
if (n > 1)
putc('\n', f);
if ((BlkLoc(tended[1])->file.status & Fs_Write) == 0)
RunErr(213, &tended[1]);
f = BlkLoc(tended[1])->file.fd;
}
else {
if (n == 1 && (k_output.status & Fs_Write) == 0)
RunErr(-213, NULL);
if (ChkNull(tended[1]))
tended[1] = emptystr;
if (cvstr(&tended[1], sbuf) == CvtFail)
RunErr(109, &tended[1]);
putstr(f, &tended[1]);
}
}
putc('\n', f);
fflush(f);
c_exit(ErrorExit);
}
#ifdef SystemFnc
/*
* system(s) - execute string s as a system command.
*/
FncDcl(system,1)
{
char sbuf[MaxCvtLen];
char *systemstring;
/*
* Make a C-style string out of Arg1
*/
switch (cvstr(&Arg1, sbuf)) {
case Cvt: /* Already converted to a C-style string */
break;
case NoCvt:
qtos(&Arg1, sbuf);
break;
default:
RunErr(103, &Arg1);
}
systemstring = StrLoc(Arg1);
/*
* Pass the C string to the system() function and return the exit code
* of the command as the result of system().
*/
/*
* The following code is operating-system dependent [@fsys.06]. Perform system
* call. Should not get here unless system(s) is supported.
*/
#if PORT
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || MSDOS || OS2 || UNIX
MakeInt((long)((system(systemstring) >> 8) & 0377), &Arg0);
#endif /* AMIGA || MSDOS || ... */
#if ATARI_ST || VMS
MakeInt(system(systemstring), &Arg0);
#endif /* ATARI_ST || VMS */
#if HIGHC_386 || MACINTOSH
/* Should not get here */
#endif /* HIGHC_386 || MACINTOSH */
#if MVS || VM
MakeInt((long)system(systemstring), &Arg0);
#endif /* MVS || VM */
/*
* End of operating-system specific code.
*/
Return;
}
#endif /* SystemFnc */
/*
* where(file) - return current offset position in file.
*/
FncDcl(where,1)
{
FILE *fd;
long ftell();
if (Arg1.dword != D_File)
RunErr(-105, NULL);
fd = BlkLoc(Arg1)->file.fd;
if ((BlkLoc(Arg1)->file.status == 0))
Fail;
MakeInt(ftell(fd) + 1, &Arg0);
Return;
}
/*
* write(a,b,...) - write arguments.
*/
FncDclV(write)
{
register word n;
char sbuf[MaxCvtLen];
FILE *f;
#ifdef BadCode
struct descrip temp;
#endif /* BadCode */
f = stdout;
ntended = 1;
tended[1] = emptystr;
/*
* Loop through the arguments.
*/
for (n = 1; n <= nargs; n++) {
#ifdef BadCode
temp = Arg(n); /* workaround for Microsoft bug */
tended[1] = temp;
#else /* BadCode */
tended[1] = Arg(n);
#endif /* BadCode */
if (tended[1].dword == D_File) { /* Current argument is a file */
/*
* If this is not the first argument, output a newline to the current
* file and flush it.
*/
if (n > 1) {
putc('\n', f);
fflush(f);
}
/*
* Switch the current file to the file named by the current argument
* providing it is a file. tended[1] is made to be a empty string to
* avoid a special case.
*/
if ((BlkLoc(tended[1])->file.status & Fs_Write) == 0)
RunErr(213, &tended[1]);
f = BlkLoc(tended[1])->file.fd;
tended[1] = emptystr;
}
else { /* Current argument is a string */
/*
* On first argument, check to be sure that &output is open
* for output.
*/
if (n == 1 && (k_output.status & Fs_Write) == 0)
RunErr(-213, NULL);
/*
* Convert the argument to a string, defaulting to a empty string.
*/
if (ChkNull(tended[1]))
tended[1] = emptystr;
if (cvstr(&tended[1], sbuf) == CvtFail)
RunErr(109, &tended[1]);
/*
* Output the string.
*/
if (putstr(f, &tended[1]) == Failure)
RunErr(-214, NULL);
}
}
/*
* Append a newline to the file and flush it.
*/
putc('\n', f);
if (ferror(f))
RunErr(-214, NULL);
fflush(f);
/*
* Return the last argument.
*/
ntended = 0;
Arg(0) = Arg(n - 1);
Return;
}
/*
* writes(a,b,...) - write arguments without newline terminator.
*/
FncDclV(writes)
{
register word n;
char sbuf[MaxCvtLen];
FILE *f;
#ifdef BadCode
struct descrip temp;
#endif /* BadCode */
f = stdout;
ntended = 1;
tended[1] = emptystr;
/*
* Loop through the arguments.
*/
for (n = 1; n <= nargs; n++) {
#ifdef BadCode
temp = Arg(n); /* workaround for Microsoft bug */
tended[1] = temp;
#else /* BadCode */
tended[1] = Arg(n);
#endif /* BadCode */
if (tended[1].dword == D_File) { /* Current argument is a file */
/*
* Switch the current file to the file named by the current argument
* providing it is a file. tended[1] is made to be a empty string to
* avoid a special case.
*/
if ((BlkLoc(tended[1])->file.status & Fs_Write) == 0)
RunErr(213, &tended[1]);
f = BlkLoc(tended[1])->file.fd;
tended[1] = emptystr;
}
else { /* Current argument is a string */
/*
* On first argument, check to be sure that &output is open
* for output.
*/
if (n == 1 && (k_output.status & Fs_Write) == 0)
RunErr(-213, NULL);
/*
* Convert the argument to a string, defaulting to a empty string.
*/
if (ChkNull(tended[1]))
tended[1] = emptystr;
if (cvstr(&tended[1], sbuf) == CvtFail)
RunErr(109, &tended[1]);
/*
* Output the string and flush the file.
*/
if (putstr(f, &tended[1]) == Failure)
RunErr(-214, NULL);
#ifndef WATERLOO_C_V3
fflush(f);
#endif /* WATERLOO_C_V3 */
}
}
/*
* Return the last argument.
*/
ntended = 0;
Arg(0) = Arg(n - 1);
Return;
}
#ifdef KeyboardFncs
/*
* getch() - return a character from console.
*/
FncDcl(getch,0)
{
unsigned char c;
int i;
i = getch();
if (i<0)
Fail;
if (strreq((word)1) == Error)
RunErr(0, NULL);
c = (unsigned char) i;
StrLoc(Arg0) = alcstr((char *)&c,(word)1);
StrLen(Arg0) = 1;
Return;
}
/*
* getche() -- return a character from console with echo.
*/
FncDcl(getche,0)
{
unsigned char c;
int i;
i = getche();
if (i<0)
Fail;
if (strreq((word)1) == Error)
RunErr(0, NULL);
c = (unsigned char) i;
StrLoc(Arg0) = alcstr((char *)&c,(word)1);
StrLen(Arg0) = 1;
Return;
}
/*
* kbhit() -- Check to see if there is a keyboard character waiting to
* be read.
*/
FncDcl(kbhit,0)
{
if (kbhit()) {
Arg0 = nulldesc;
Return;
}
else Fail;
}
#endif /* KeyboardFncs */